'''
获取到所有的PR信息，找出每一个PR创建的时间，以及在该PR创建时间那个时刻仍处于open状态的pr，
然后将这个时刻还处于open状态的pr作为输入X。
FIFO算法，根据pr创建的时间先创建，放在最前面，这样对上述pr列表进行排序。FIFOY
真实排序：在该时刻之后，该X中，被相应，或者被关闭或者被合并等发生改变的时间，根据该时间顺序进行排序，进而获取真实排序TRUEY
将FIFOY，与TRUEY进行比较，通过NDcg进行比较，判断排序效果
'''
from datetime import timedelta

import data_processing_engineering.get_data_from_database.database_connection as dbConnection

from evaluation_index.Kendall_tau_distance import kendall_tau_distance
from evaluation_index.mrr import mrr
from utils.date_utils.date_function import get_waiting_time, get_close_pr_time
import csv
from evaluation_index.ndcg import ndcg
# Python的标准库linecache模块非常适合这个任务
import linecache
import os

import pandas as pd
# 增加代码的可读性
from utils.path_exist import path_exists_or_create


def prepare_temp_file(temp_data_path, origin_data_path, open_pr_index_list, day):
    file = open(temp_data_path, 'w+')
    for i in range(len(open_pr_index_list)):
        s = getline(origin_data_path, open_pr_index_list[i] + 1)
        file.write(s)
    file.close()
    print("保存第 " + str(day) + " 天的临时文件成功")


# 可显示使用循环, 注意enumerate从0开始计数，而line_number从1开始
def getline(the_file_path, line_number):
    if line_number < 1:
        return ''
    for cur_line_number, line in enumerate(open(the_file_path, 'rU')):
        if cur_line_number == line_number - 1:
            return line
    return ''


# 从模型计算出的排序文件获取模型的排序结果
def get_result_list(the_file_path):
    result = []
    for line in open(the_file_path):
        line_str = line.split(" ")
        result.append(int(line_str[2]))
    return result


# 对模型进行调用，同时将数据写入到文件中，方便后续统计
def alg_model_result(result_data_path, top_k, reversed, alg_name, repo_name, start_day, end_day):
    result_data = pd.read_excel(result_data_path)
    ndcg_list = []
    day_list = []
    mrr_list = []
    kendall_list = []
    open_pr_count_byday = []
    max_day = None
    min_day = None

    # 获取每天处于open状态的PR
    day_open_pr_data = {}
    for i in range((end_day - start_day).days + 1):
        day = start_day + timedelta(days=i)
        day_open_pr_data[str(day)] = []

    for index, row in result_data.iterrows():
        pr_result = {}
        pr_number = row['pr_number']
        pr_result[pr_number] = {}
        pr_result[pr_number]['created_time'] = pd.to_datetime(row['created_time'])
        pr_result[pr_number]['closed_time'] = pd.to_datetime(row['closed_time'])
        pr_result[pr_number]['merged_time'] = pd.to_datetime(row['merged_time'])
        pr_result[pr_number][alg_name] = row[alg_name]
        pr_result[pr_number]['original_rank'] = row['original_rank']
        pr_start_day = pr_result[pr_number]['created_time']
        if row['merged_time'].date() is not None and pd.isnull(row['merged_time'].date()) is False:
            pr_end_day = pr_result[pr_number]['merged_time']
        elif row['closed_time'].date() is not None and pd.isnull(row['closed_time'].date()) is False:
            pr_end_day = pr_result[pr_number]['closed_time']
        else:
            pr_end_day = end_day
        # 获取每天处于open状态的PR
        for i in range((pr_end_day - pr_start_day).days + 1):
            day = pr_start_day + timedelta(days=i)
            day = str(day.date()) + " 00:00:00"
            if day in day_open_pr_data.keys():
                day_open_pr_data[day].append(pr_result)
    # 只统计有PR的日期
    day_count = 0
    for day in day_open_pr_data.keys():
        pr_list = day_open_pr_data[day]
        if pr_list.__len__() == 0:
            continue
        day_count = day_count + 1
        print("当前日期：", day)

        # 存储算法的排序列表
        rank_sort = []
        rank_value_sort = []
        rank_dict = {}
        # 存储真实的排序列表
        true_sort = []
        true_value_sort = []
        true_dict = {}
        for pr in pr_list:
            for key in pr.keys():
                true_dict[key] = pr[key]['original_rank']
                rank_dict[key] = pr[key][alg_name]
        # 将true_dict按照value进行排序，并将排序后的key存储到true_sort中
        true_sort = sorted(true_dict, key=true_dict.__getitem__, reverse=reversed)
        # 将rank_dict按照value进行排序，并将排序后的key存储到rank_sort中
        rank_sort = sorted(rank_dict, key=rank_dict.__getitem__, reverse=reversed)
        # 根据top_k判断是否需要截取，并截断前top_k个的PR——number
        if top_k is not None and top_k < rank_sort.__len__():
            rank_sort = rank_sort[0:top_k]
        for temp_rank_pr in rank_sort:
            rank_value_sort.append(true_dict[temp_rank_pr])
            true_value_sort.append(true_dict[temp_rank_pr])
        true_value_sort.sort(reverse=reversed)

        ndcg_num = ndcg(true_value_sort, rank_value_sort, rank_value_sort.__len__(), form="exp")
        mrr_num = mrr(true_value_sort, rank_value_sort)
        kendall_num = kendall_tau_distance(true_value_sort, rank_value_sort)
        # print("pr_number排序:", sort_result)
        print("存储算法的排序列表rank_sort:", rank_sort)
        print("存储真实的排序列表true_sort:", true_sort)
        print("存储算法的排序列表rank_value_sort:", rank_value_sort)
        print("存储真实的排序列表true_value_sort:", true_value_sort)
        print("ndcg_num:", ndcg_num)
        print("mrr_num:", mrr_num)
        print("kendall_num:", kendall_num)
        day_list.append(day)
        ndcg_list.append(ndcg_num)
        mrr_list.append(mrr_num)
        kendall_list.append(kendall_num)
        open_pr_count_byday.append(pr_list.__len__())

    headers = ['日期', '当日openPR个数',
               'ndcg',
               'mrr',
               'kendall_tau_distance'
               ]
    row_data = []
    for i in range(len(day_list) + 1):
        tmp = []
        if i < len(day_list):
            tmp.append(day_list[i])
            tmp.append(open_pr_count_byday[i])
            tmp.append(ndcg_list[i])
            tmp.append(mrr_list[i])
            tmp.append(kendall_list[i])
        else:
            tmp.append("平均值")
            tmp.append(" ")
            tmp.append(sum(ndcg_list) / len(ndcg_list))
            tmp.append(sum(mrr_list) / len(mrr_list))
            tmp.append(sum(kendall_list) / len(kendall_list))
        row_data.append(tmp)
    print(row_data)
    # 保存数据到csv文件
    result_path = "./rank_model/" + repo_name + "/result/rank_eval/"
    path_exists_or_create(result_path)
    with open(result_path + repo_name + "_" + str(reversed) + "_" + alg_name + "_result.csv",
              'w', encoding='utf-8', newline='') as f:
        writer = csv.writer(f, dialect='excel')
        writer.writerow(headers)
        for item in row_data:
            writer.writerow(item)
    return None


# Press the green button in the gutter to run the script.
if __name__ == '__main__':

    repo_list = ["tensorflow"]
    for repo_name in repo_list:
        # ranklib所能调的库
        alg_dict = {
            0: "MART",
            1: "RankNet",
            2: "RankBoost",
            3: "AdaRank",
            4: "Coordinate_Ascent",
            6: "LambdaMART",
            7: "ListNet",
            8: "Random_Forests",
            9: "FIFO",
            10: "SMF"
        }
        # reversed为True是优先级越大越好，False是优先级越小越好
        reversed_list = [False, True]
        for alg_index in alg_dict.keys():
            alg_name = alg_dict.get(alg_index)
            result_path = "./sim_data/" + repo_name + "/"
            path_exists_or_create(result_path)
            result_data_path = result_path + repo_name + "_pr_mP.xlsx"
            top_k = 20
            for reversed in reversed_list:
                alg_model_result(result_data_path, top_k, reversed, alg_name, repo_name, pd.to_datetime("2022-01-1"),
                                 pd.to_datetime("2022-12-31"))
